""" 
A quick script for uploading built Persimmon UI resources to 
    ART-Pi through built-in FTP, assuming ART-Pi auto-connects
    to WiFi on boot. 

Note: RT-Thread's agile_ftp implementation uses active mode
    See: https://github.com/loogg/agile_ftp

Usage: 
    $ python ftp_upload.py path_to_persimmon_project [subdir_under_flash]

Example: 
    $ python ftp_upload.py persimmon_proj test -a 192.168.0.34 -v 1 -u admin -p itsapassword

Options: 
    -a FTP server IP address
    -v Verbose level (0(default) ~ 2)
    -u Username
    -p Password
    -c Config file (not implemented yet)

"""

import argparse
from pathlib import Path
from ftplib import FTP, error_perm

OPT = None


def parse_init():
    parser = argparse.ArgumentParser(
        description="Import given directory to ART-Pi FTP Server"
    )

    # Positional arguments
    parser.add_argument("source", help="Path to the directory to be uploaded")
    parser.add_argument(
        "subdir", help="Subdirectory under /flash, e.g. test => /flash/test"
    )

    # Optional arguments
    parser.add_argument("-a", "--address", help="Server IP address", required=True)
    parser.add_argument("-p", "--port", help="Server port (deprecated)")
    parser.add_argument(
        "-v", "--verbose", help="Verbose level (0~2)", type=int, default=0
    )
    parser.add_argument("-U", "--username", help="FTP login username", default="loogg")
    parser.add_argument("-P", "--password", help="FTP login password", default="loogg")
    parser.add_argument(
        "--storage", help="Storage device (flash / sdcard)", default="flash"
    )
    parser.add_argument("-n", "--dry-run", help="Dryrun", action="store_true")

    args = parser.parse_args()
    return args


def upload_tree(ftp: FTP, path, root=False):
    p = Path(path)
    p_abs = p.resolve()
    relative_root = Path(OPT.source)

    print(f"MKDIR {OPT.subdir}\{p_abs.relative_to(relative_root.resolve())}")
    if not OPT.dry_run:
        if not root:
            ftp.mkd(p.name)
            ftp.cwd(p.name)

    for dir in [entry for entry in p_abs.iterdir() if entry.is_dir()]:
        upload_tree(ftp, dir)

    for item in [entry for entry in p_abs.iterdir() if not entry.is_dir()]:
        print(f"UPLOAD {OPT.subdir}\{item.relative_to(relative_root.resolve())}")
        if not OPT.dry_run:
            ftp.storbinary("STOR " + item.name, open(item, "rb"))

    if not OPT.dry_run:
        ftp.cwd("..")


def transfer_init(args):
    ftp_i = FTP(host=args.address, user=args.username, passwd=args.password)
    ftp_i.set_debuglevel(args.verbose)
    ftp_i.set_pasv(False)

    ftp_i.cwd(f"/{args.storage}")

    target = Path(args.subdir)
    ftp_i.mkd(target.name)
    ftp_i.cwd(target.name)
    upload_tree(ftp_i, args.source, root=True)

    ftp_i.quit()


if __name__ == "__main__":
    OPT = parse_init()
    transfer_init(OPT)
